<script lang="ts" setup>
import type {
  UploadUserFile,
  UploadRequestHandler,
  UploadProps,
  UploadFile,
  UploadFiles,
  UploadRequestOptions,
  UploadRawFile,
} from "element-plus";
import { ElNotification } from "element-plus";
import { upload as uploadFile } from "@/utils/minio-upload";

const action = ref(""),
  dialogImageUrl = ref(""),
  showViewer = ref(false);

const uploadRef = ref();

const props = defineProps({
  modelValue: {
    type: [ Array, String ],
    default: () => {
      return [];
    },
  },
  limit: {
    type: Number,
    default: 1,
  },
  filePath: {
    type: String,
    default: "marketing-center/",
  },
  accept: {
    type: String,
    default: "image/*",
  },
  //第一张图是否需要添加文字
  isAddFirstText: {
    type: Boolean,
    default: false,
  },
  fistText: {
    type: String,
    default: "第一张图",
  },
});

const fileList: any = computed(() => {
  let files: any = props.modelValue,
    result: UploadUserFile[] = [];
  if (files instanceof Array) {
    files.forEach((item) => {
      result.push({
        url: item.url || item,
        name: item.name || (item.url || item).split("/").pop(),
      });
    });
  } else if (typeof files === "string" && files !== "") {
    result.push({
      url: files,
      name: files.split("/").pop(),
    } as UploadFile);
    if (props.limit > 1) {
      console.warn(
        `The value of the attribute 'limit' is ${props.limit}, and the modelvalue needs to be passed in the Array type`
      );
    }
  }
  return result;
});

const firstTextStr = computed(() => {
  return "red";
});

const emits = defineEmits([ "update:modelValue", "success", "change" ]);

const upload: UploadRequestHandler = ({ file }: UploadRequestOptions) => {
  return new Promise(async (resolve, reject) => {
    try {
      const result: any = await uploadFile(file, props.filePath);
      resolve(result);
    } catch (e) {
      reject();
    }
  });
};

const remove = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  let fileList = uploadFiles.map((file: any) => {
    return file.response
      ? { name: file.response.name, url: file.response.url }
      : file;
  });
  let formatList = formatValue(fileList);
  emits("update:modelValue", formatList);
  emits("change", formatList);
};

const success = (
  response: any,
  uploadFile: UploadFile,
  uploadFiles: UploadFiles
) => {
  let fileList = uploadFiles.map((file: any) => {
    return {
      name: file.name,
      url: (file.response && file.response.url) || file.url,
    };
  });
  let formatList = formatValue(fileList);
  emits("update:modelValue", formatList);
  emits("success", {
    name: uploadFile.name,
    url: (uploadFile.response as any).url,
  });
  emits("change", formatList);
};

const formatValue = (fileList: Array<any>) => {
  let files: any = props.modelValue || "",
    result;
  if (files instanceof Array) {
    result = [];
    if (props.modelValue[0] && typeof props.modelValue[0] === "object") {
      result = fileList;
    } else {
      result = fileList.map((item) => item.url);
    }
  } else if (typeof files === "string") {
    if (props.limit == 1) {
      result = fileList[0] ? fileList[0].url : "";
    } else {
      result = fileList.map((item) => {
        return item.url;
      });
    }
  }
  return result;
};

const handleExceed = () => {
  ElNotification.warning(`限制上传${props.limit}个文件`);
};

const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  showViewer.value = true;
};

const clearFiles = () => {
  uploadRef.value.clearFiles();
};

const handleRemove = (file: UploadFile | UploadRawFile) => {
  uploadRef.value.handleRemove(file);
};

// 手动触发upload
const selectFile = () => {
  uploadRef.value.click();
}

defineExpose({ clearFiles, handleRemove, selectFile });
</script>
<template>
  <el-upload
    ref="uploadRef"
    :action="action"
    :limit="limit"
    :http-request="upload"
    :file-list="fileList"
    :accept="accept"
    :on-exceed="handleExceed"
    :on-remove="remove"
    :on-success="success"
    :on-preview="handlePictureCardPreview"
    :class="{
      'hidden-add': fileList && fileList.length >= limit,
      custom_upload: props.isAddFirstText,
    }"
    v-bind="$attrs"
  >
    <slot>
      <el-button type="primary">
        点击上传
      </el-button>
    </slot>
    <template #file="{ file }">
      <slot
        name="file"
        :file="file"
      />
    </template>
  </el-upload>
  <el-image-viewer v-if="showViewer" :initial-index="0" :url-list="[dialogImageUrl]" :teleported="true" @close="showViewer = false">
  </el-image-viewer>
</template>
<style lang="scss" scoped>
.custom_upload {
  :deep(.el-upload-list--picture-card) {
    .el-upload-list__item.is-success:nth-of-type(1) {
      position: relative;

      &::after {
        position: absolute;
        content: "封面图";
        left: 0;
        right: 0;
        bottom: 0;
        padding: 10px;
        background-color: #000;
        opacity: 0.15;
        color: #fff;
        text-align: center;
      }
    }
  }
}

.hidden-add {
  :deep(.el-upload--picture-card) {
    display: none;
  }
}
</style>
